#include "Mesh.h"
#include "IndexBuffer.h"
#include "Texture2D.h"
#include "VertexArray.h"
#include "VertexBuffer.h"
#include "VertexBufferLayout.h"
#include <glad/glad.h>
#include <string>
#include <iostream>

Mesh::Mesh(std::vector<OpenGLVertex> vertices, std::vector<unsigned int> indices, std::vector<OpenGLTexture> textures) :
    m_vertices(vertices), m_indices(indices), m_textures(textures)
{
    m_vao = new VertexArray();
    m_vbo = new VertexBuffer(m_vertices.data(), m_vertices.size() * sizeof(OpenGLVertex));
    m_ebo = new IndexBuffer(m_indices.data(), m_indices.size());
    setupMesh();
}

Mesh::~Mesh()
{
    delete m_vao;
    delete m_vbo;
    delete m_ebo;
}

void Mesh::setupMesh()
{
    VertexBufferLayout layout(sizeof(OpenGLVertex));
    layout.addAttribute(0, 3, GL_FLOAT, 0);
    layout.addAttribute(1, 3, GL_FLOAT, offsetof(OpenGLVertex, normal));
    layout.addAttribute(2, 2, GL_FLOAT, offsetof(OpenGLVertex, texCoords));
    m_vao->addBuffer(*m_vbo, layout);
}

void Mesh::draw(ShaderProgram &program)
{
    unsigned int diffuseNr  = 1;
    unsigned int specularNr = 1;
    for (unsigned int i = 0; i < m_textures.size(); i++) {
        glActiveTexture(GL_TEXTURE0 + i);
        std::string number;
        std::string name = m_textures[i].type;
        if (name == "diffuse")
            number = std::to_string(diffuseNr++);
        else if (name == "specular")
            number = std::to_string(specularNr++);

        program.setUniform1i("u_material" + number + "." + name, i);
        glBindTexture(GL_TEXTURE_2D, m_textures[i].id);
    }
    glActiveTexture(GL_TEXTURE0);

    m_vao->bind();
    glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_INT, 0);
    m_vao->unbind();
}